;; Install packages in list
(require 'package)
(setq package-list '(function-args rcirc-color rcirc-alertify rcirc-styles rainbow-delimiters paredit ido-ubiquitous smex projectile magit clojure-mode clojure-mode-extra-font-locking cider yasnippet latex-preview-pane auctex emacs-eclim auto-complete))
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/")
	     '("gnu" . "http://elpa.gnu.org/packages/"))
(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))
(dolist (package package-list)
  (unless (package-installed-p package)
    (package-install package)))


;; Use semantic and function-args for completion in c/c++
(require 'cc-mode)
(require 'semantic)
(require 'semantic/bovine/gcc)
(add-to-list 'semantic-default-submodes 'global-semanticdb-minor-mode)
(add-to-list 'semantic-default-submodes 'global-semantic-idle-local-symbol-highlight-mode)
(add-to-list 'semantic-default-submodes 'global-semantic-idle-scheduler-mode)
(add-to-list 'semantic-default-submodes 'global-semantic-idle-summary-mode)
(semantic-mode 1)
(global-ede-mode t)
(ede-enable-generic-projects)
(define-key c-mode-map  (kbd "C-c , h") 'semantic-ia-fast-jump)
(define-key c++-mode-map  (kbd "C-c , h") 'semantic-ia-fast-jump)
;; (semantic-add-system-include "~/include")
(require 'function-args)
(fa-config-default)
(projectile-global-mode)
(ede-cpp-root-project "contiki"
                      :file "~/Code/contiki/Makefile.include"
                      :include-path '("/*"
                                      "/core")
                      ;; :system-include-path '("~/include")
                      )


;; Enable spell-checking using aspell
(setq-default ispell-program-name "aspell")
(setq ispell-list-command "--list")

;; ibuffer Groups
(require 'ibuffer nil t)
(setq-default ibuffer-saved-filter-groups
              (quote (("default"
                       ("dired" (mode . dired-mode))
                       ("org"   (mode . org-mode))
                       ("latex" (mode . latex-mode))
                       ("java"  (mode . java-mode))
                       ("clojure" (mode . clojure-mode))
                       ("C/C++" (or
                                (mode . cc-mode)
                                (mode . c-mode)
                                (mode . c++-mode)))
                       ("magit" (name . "^\\*magit"))
		       ("rcirc" (mode . rcirc-mode))
		       ("emacs" (or
                                (name . "^\\*scratch\\*$")
                                (name . "^\\*Messages\\*$")))
		       ("shell commands" (name . "^\\*.*Shell Command\\*"))))))
(add-hook 'ibuffer-mode-hook
          (lambda ()
            (ibuffer-switch-to-saved-filter-groups "default")))
(global-set-key (kbd "\C-x \C-b") 'ibuffer)


;; rcirc
(require 'rcirc)
;; Don't print /away messages.
(defun rcirc-handler-301 (process cmd sender args)
  "/away message handler.")
;; Keep input line at bottom. Use rcirc-color , rcirc-styles and omit mode.
(add-hook 'rcirc-mode-hook
	  (lambda ()
	    (set (make-local-variable 'scroll-conservatively) 8192)
	    (require 'rcirc-color)
	    (require 'rcirc-styles)
	    (setq rcirc-omit-mode nil)
	    (rcirc-omit-mode)))
;; Fill column to wrap up lines
(setq rcirc-fill-flag t)
(setq rcirc-fill-column 80)
;; Log irc channels in ~/.rcirclogs
(setq rcirc-log-directory (expand-file-name ".rcirclogs" (getenv "HOME")))
(setq rcirc-log-flag t)
(setq rcirc-log-process-buffers t)
;; Adjust the colours of one of the faces.
(set-face-foreground 'rcirc-my-nick "red" nil)
;; Include date in time stamp.
(setq rcirc-time-format "%H:%M ")
;; Change user info
(setq rcirc-default-nick "quigonjinn")
(setq rcirc-default-user-name "quigonjinn")
(setq rcirc-default-full-name "quigonjinn")
;; Join these channels at startup.
(setq rcirc-server-alist
      '(("irc.freenode.net" :port 6697 :encryption tls
	 :channels ("#emacs" "#libreboot" "#parabola" "#guix" "#rcirc" "##electronics" "##fpga" "#fsf" "#fsfe" "#grub" "#gnu" "#replicant"))))
;; Enable rcirc alerts
(require 'rcirc-alertify)
(rcirc-alertify-enable)
;; Play sound when nick is mentioned
(setq alert "/usr/share/sounds/freedesktop/stereo/message.oga")
(defun my-rcirc-print-hook (process sender response target text)
  (when (and (string-match (regexp-quote (rcirc-nick process)) text)
	     (not (string= (rcirc-nick process) sender))
	     (not (string= (rcirc-server-name process) sender)))
    (start-process "beep" nil "mplayer" (expand-file-name alert))))
(add-hook 'rcirc-print-functions 'my-rcirc-print-hook)
;; /disconnect command
(eval-after-load 'rcirc
  '(defun-rcirc-command disconnect (arg)
     "Disconnect the server process."
     (interactive "i")
     (unless process
       (error "There's no process for this target"))
     (let* ((server (car (process-contact process)))
            (port (process-contact process :service))
            (nick (rcirc-nick process))
            channels query-buffers)
       (dolist (buf (buffer-list))
         (with-current-buffer buf
           (when (eq process (rcirc-buffer-process))
             (remove-hook 'change-major-mode-hook
                          'rcirc-change-major-mode-hook)
             (if (rcirc-channel-p rcirc-target)
                 (setq channels (cons rcirc-target channels))
               (setq query-buffers (cons buf query-buffers))))))
       (delete-process process))))

;;editing
;;Hippie expand for Lisp
(global-set-key (kbd "M-/") 'hippie-expand)
(setq hippie-expand-try-functions-list
      '(try-expand-dabbrev
        try-expand-dabbrev-all-buffers
        try-expand-dabbrev-from-kill
        try-complete-lisp-symbol-partially
        try-complete-lisp-symbol))
;;Highlight matching parenthesis
(show-paren-mode 1)
;;Don't use hard tabs
(setq-default indent-tabs-mode nil)
;; put all backups in ~/.emacs.d/backups. More info:
(setq backup-directory-alist `(("." . ,(concat user-emacs-directory "backups"))))
;; comments
(defun toggle-comment-on-line ()
  "comment or uncomment current line"
  (interactive)
  (comment-or-uncomment-region (line-beginning-position) (line-end-position)))
(global-set-key (kbd "C-;") 'toggle-comment-on-line)
;; dual color rainbow!
(require 'rainbow-delimiters)
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
(require 'cl-lib)
(defvar my-paren-dual-colors
  '("#a07070" "#7070a0"))
(cl-loop
 for index from 1 to rainbow-delimiters-max-face-count
 do
 (set-face-foreground
  (intern (format "rainbow-delimiters-depth-%d-face" index))
  (elt my-paren-dual-colors
       (if (cl-evenp index) 0 1))))
;; use 2 spaces for tabs
(defun die-tabs ()
  (interactive)
  (set-variable 'tab-width 2)
  (mark-whole-buffer)
  (untabify (region-beginning) (region-end))
  (keyboard-quit))
;; show unncessary whitespace that can mess up  diff
(add-hook 'prog-mode-hook (lambda () (interactive) (setq show-trailing-whitespace 1)))
;; use yasnippet globally
(require 'yasnippet)
(yas-global-mode 1)
;; Interactive compile shortcut
(global-set-key (kbd "<f5>") (lambda ()
                               (interactive)
                               (setq-local compilation-read-command nil)
                               (call-interactively 'compile)))
;; gdb setup
(setq
 ;; use gdb-many-windows by default
 gdb-many-windows t
 ;; Non-nil means display source file containing the main routine at startup
 gdb-show-main t
 )


;; ido-mode & smex
(ido-mode t)
;; This allows partial matches
(setq ido-enable-flex-matching t)
;; Turn this behavior off because it's annoying
(setq ido-use-filename-at-point nil)
;; only match files in the current directory displayed in the minibuffer
(setq ido-auto-merge-work-directories-length -1)
;; This enables ido in all contexts where it could be useful
(ido-ubiquitous-mode 1)
;; Enhances M-x to allow easier execution of commands.
(setq smex-save-file (concat user-emacs-directory ".smex-items"))
(smex-initialize)
(global-set-key (kbd "M-x") 'smex)
(defadvice smex (around space-inserts-hyphen activate compile)
        (let ((ido-cannot-complete-command
               `(lambda ()
                  (interactive)
                  (if (string= " " (this-command-keys))
                      (insert ?-)
                    (funcall ,ido-cannot-complete-command)))))
          ad-do-it))
(defun smex-update-after-load (unused)
      (when (boundp 'smex-cache)
        (smex-update)))
(add-hook 'after-load-functions 'smex-update-after-load)

;; elisp-editing paredit & eldoc
;; Automatically load paredit when editing a lisp file
(autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t)
(add-hook 'emacs-lisp-mode-hook       #'enable-paredit-mode)
(add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode)
(add-hook 'ielm-mode-hook             #'enable-paredit-mode)
(add-hook 'lisp-mode-hook             #'enable-paredit-mode)
(add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode)
(add-hook 'scheme-mode-hook           #'enable-paredit-mode)
;; eldoc-mode shows documentation in the minibuffer when writing code
(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
(add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode)
(add-hook 'ielm-mode-hook 'turn-on-eldoc-mode)

;;;;
;; Clojure
;;;;
;; Enable paredit for Clojure
(add-hook 'clojure-mode-hook 'enable-paredit-mode)
;; This is useful for working with camel-case tokens, like names of
;; Java classes (e.g. JavaClassName)
(add-hook 'clojure-mode-hook 'subword-mode)
;; A little more syntax highlighting
(require 'clojure-mode-extra-font-locking)
;; syntax hilighting for midje
(add-hook 'clojure-mode-hook
          (lambda ()
            (setq inferior-lisp-program "lein repl")
            (font-lock-add-keywords
             nil
             '(("(\\(facts?\\)"
                (1 font-lock-keyword-face))
               ("(\\(background?\\)"
                (1 font-lock-keyword-face))))
            (define-clojure-indent (fact 1))
            (define-clojure-indent (facts 1))))
;; Cider
;; provides minibuffer documentation for the code you're typing into the repl
(add-hook 'cider-mode-hook 'cider-turn-on-eldoc-mode)
;; go right to the REPL buffer when it's finished connecting
(setq cider-repl-pop-to-buffer-on-connect t)
;; When there's a cider error, show its buffer and switch to it
(setq cider-show-error-buffer t)
(setq cider-auto-select-error-buffer t)
;; Where to store the cider history.
(setq cider-repl-history-file "~/.emacs.d/cider-history")
;; Wrap when navigating history.
(setq cider-repl-wrap-history t)
;; enable paredit in your REPL
(add-hook 'cider-repl-mode-hook 'paredit-mode)
;; Use clojure mode for other extensions
(add-to-list 'auto-mode-alist '("\\.edn$" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.boot$" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.cljs.*$" . clojure-mode))
(add-to-list 'auto-mode-alist '("lein-env" . enh-ruby-mode))
;; key bindings
(defun cider-refresh ()
  (interactive)
  (cider-interactive-eval (format "(user/reset)")))
(defun cider-user-ns ()
  (interactive)
  (cider-repl-set-ns "user"))
;; openSCAD wrapper function
;; to use add [scad-clj "0.5.1"] as project dependency
(defun spit-scad-last-expression ()
  (interactive)
  (cider-interactive-eval
   (format
    "(require 'scad-clj.scad)
       (spit \"repl.scad\"
             (scad-clj.scad/write-scad %s))"
    (cider-last-sexp))))
(eval-after-load 'cider
  '(progn
     (define-key clojure-mode-map (kbd "C-M-r") 'cider-refresh)
     (define-key clojure-mode-map (kbd "C-c u") 'cider-user-ns)
     (define-key cider-mode-map (kbd "C-c u") 'cider-user-ns)
     (define-key cider-mode-map (kbd "C-c 3") 'spit-scad-last-expression)))

;; Load org-mode from git, to enable org-babel-clojure evaluation using cider
(let ((default-directory  "~/.emacs.d/org-mode/"))
  (setq load-path
        (append
         (let ((load-path  (copy-sequence load-path)))
           (normal-top-level-add-to-load-path '("lisp")))
         load-path)))
(require 'org)
(require 'ob-clojure)
(setq org-babel-clojure-backend 'cider)
(require 'cider)
;; Enable org-babel evaluation
(custom-set-variables
'(org-babel-load-languages (quote ((emacs-lisp . t) (latex . t) (clojure . t))))
;; Latex packages
'(org-latex-packages-alist (quote (("\"\"" "\"circuitikz\"" nil)))))
;; Latex macros to include .pdf from result, and delete it. Use together with :exports none
(fset 'remove-babel-source-result-latex
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([134217747 94 46 42 92 backspace 35 92 43 66 69 71 73 78 95 76 97 84 101 88 return 19 91 91 102 105 108 101 58 return 2 2 2 2 2 2 2 67108896 16 16 1 16 23 134217747 94 46 42 35 92 43 69 78 68 95 76 97 84 101 88 return 1 67108896 14 14 23] 0 "%d")) arg)))
(global-set-key [24 11 48] 'remove-babel-source-result-latex) ;;"C-x C-k 0"

(fset 'remove-org-file-pdf
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([134217747 94 46 42 102 105 108 101 58 46 42 92 46 112 100 102 93 93 return 1 67108896 14 23] 0 "%d")) arg)))
(global-set-key [24 11 57] 'remove-org-file-pdf) ;;"C-x C-k 9"


;; Eclim (Java) configuration
(require 'eclim)
(global-eclim-mode)
(require 'eclimd)
;; Autocomplete
(require 'ac-emacs-eclim-source)
(ac-emacs-eclim-config)
(add-hook 'java-mode-hook 'auto-complete-mode)


;; Hide menu-bar, scroll-bar, tool-bar. Uniquify buffer-name. Blink-cursor nil.
(custom-set-variables
 '(blink-cursor-mode nil)
 '(menu-bar-mode nil)
'(scroll-bar-mode nil)
 '(tool-bar-mode nil)
 '(uniquify-buffer-name-style (quote post-forward-angle-brackets) nil (uniquify))
 '(vhdl-makefile-generation-hook
   (quote
    ((lambda nil
       (re-search-backward "^# Rule for compiling entire design")
       (setq x
	     (downcase
	      (file-name-base
	       (buffer-file-name
		(window-buffer
		 (minibuffer-selected-window))))))
       (insert "# Simulate testbench and create the executable
sim :
	ghdl -m --workdir=work --ieee=synopsys -fexplicit " x "
	mv " x " work/" x "

#Run simulation and save the vcd output compressed
run :
	work/" x " --assert-level=error --vcdgz=work/" x ".vcdgz

#View simulation results in gtw-wave
view :
	gunzip --stdout work/" x ".vcdgz | gtkwave --vcd

")
       (re-search-forward "^	-rm -f $(ALL_UNITS)")
       (insert "
	 rm -rf work
	 rm e~" x ".o
	 rm Makefile~"))))))


;; Faces
(custom-set-faces
 '(default ((t (:inherit nil :stipple nil :background "#101010" :foreground "#d2c5bc" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 113 :width normal :foundry "unknown" :family "DejaVu Sans Mono")))))
